{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [2010-10-09 function/bind的救赎](https://blog.csdn.net/myan/article/details/5928531)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 设计原则不仅限于面向对象体系"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们常见的 SOLID、迪米特法则等确实诞生于 OO 背景，但它们只是巨大设计原则版图中的一个子集。按层次与范式，我们可以看到更多原则："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**范式级原则（与编程范式相关）**\n",
    "\n",
    "| 范式                        | 核心观念                           | 典型原则/实践                                                |\n",
    "| --------------------------- | ---------------------------------- | ------------------------------------------------------------ |\n",
    "| **过程式**                  | 顺序、分支、循环组织程序           | 结构化编程、分层分模块、KISS（Keep It Simple, Stupid）、DRY（Don't Repeat Yourself） |\n",
    "| **函数式**                  | 函数是第一等公民，强调不可变性     | 纯函数、引用透明性、函数组合、管道化数据流、幂等性、Monad 等代数律 |\n",
    "| **数据驱动 / 数据导向设计** | 描述数据布局与访问模式优先于类结构 | 数据局部性、缓存友好、组件-实体系统（ECS）                   |\n",
    "| **消息驱动 / Actor 模型**   | 并发通过消息传递协作               | 非共享状态、Back-pressure 控制、监督策略（Supervisor Hierarchy） |\n",
    "| **事件溯源 / CQRS**         | 读写分离、事件流是事实来源         | 事件不可变、Command 与 Query 分离、Rebuild/Replay 能力       |\n",
    "\n",
    "> 例如你引用的文章中强调 Smalltalk/Objective-C 的动态消息发送，实质上就是将“消息通信”看作一等公民的设计原则，与面向对象的“类层次结构”是两个不同层次的讨论。我们在设计时完全可以把“消息传递”和“组件协作接口”作为首要原则，而不是纠结继承结构。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**跨范式通用原则**\n",
    "\n",
    "- **Separation of Concerns（关注点分离）**<br/>\n",
    "   在结构化编程、函数式、OO、前端工程化等领域都适用。MVC 就是它的具象化版本之一，但你可以不使用 MVC 仍然贯彻关注点分离（如 React 中的容器组件/展示组件划分、后端的 Hexagonal Architecture）。\n",
    "- **层次化（Layering）与 Ports-Adapters（六边形架构）**<br/>\n",
    "   让核心业务逻辑与外部世界通过接口耦合，面向接口编程正是这种思想。无论 OO 还是函数式，都可以通过定义接口或类型类保持“内核与外设”解耦。\n",
    "- **依赖管理原则**<br/>\n",
    "   包括依赖图的 DAG 化、DI（依赖注入）、Service Locator、甚至脚本语言里通过高阶函数传递行为，都旨在让模块依赖明确、可酌情替换。\n",
    "- **演进式设计（Evolutionary Design）与 YAGNI（You Aren’t Gonna Need It）**<br/>\n",
    "   强调不要过度设计，先让系统跑起来，再在反馈中提炼模型。很多成功的函数式项目就是这样，先以不可变数据+函数组合交付，再决定是否引入复杂抽象。\n",
    "- **可观测性（Observability）与可测试性（Testability）**<br/>\n",
    "   不管 OO 还是非 OO，能否监控、冷启动、测试、灰度发布，都与设计原则紧密相关。Contract Testing、Property-based Testing、 async logging 等都属于设计层面的考量。\n",
    "- **可演算性/可检验性**<br/>\n",
    "   在安全关键系统中，形式化验证、模型检查、类型系统（如 Haskell、Rust）本身就是设计原则。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 面向接口是否意味着“无需设计模式”？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**“面向接口”是一种原则，不是特定范式**\n",
    "\n",
    "面向接口编程（Interface-Oriented Design）强调 *只承诺行为契约，不暴露实现细节*。这可以在任何范式中实现：\n",
    "\n",
    "- 在 C++／Rust 中通过抽象类/概念/traits；\n",
    "- 在函数式语言中用类型类或 record-of-functions；\n",
    "- 在动态语言中利用 duck typing，只要满足协议即可。\n",
    "\n",
    "“接口优先”的设计更容易拥抱你引用的那篇文章所推崇的概念：**对象/组件在消息层面协作，而不是先纠缠于类图。** 在这种视角下，设计模式不再是必需品——只要契约清晰、组合灵活，就能解决很多问题。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**必须使用“设计模式”吗？**\n",
    "\n",
    "- **不是必须。** 设计模式是最佳实践的总结，一旦语言特性直接支持某种抽象（如 C++20 的 `std::function`/lambda 可以直接做 delegate），可能就不需要再显式“套模式”。\n",
    "- **但模式仍然有价值**：\n",
    "  - 提供团队间共通语言（术语方便沟通）。\n",
    "  - 在缺乏语言原生支持时，模式是折中方案。\n",
    "  - 许多模式反映的是跨范式思想，例如策略模式对应函数式的“传入函数作为参数”，观察者模式对应消息发布订阅模型。\n",
    "\n",
    "> 你的文章引用强调的 “function/bind/回调/消息传递” —— 实际上就是用组合（高阶函数、代理、信号、消息）取代继承。我们完全可以不谈“策略模式”这个名词，但依然在做相同的事情。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 不同层次的“设计原则”一览（含非 OO）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下表按关注层次整理常见原则与实践（不限 OO）：\n",
    "\n",
    "| 层次       | 设计原则/实践                                                | 说明与范式                 |\n",
    "| ---------- | ------------------------------------------------------------ | -------------------------- |\n",
    "| **代码级** | KISS、DRY、单一权责函数、不可变数据、纯函数、Guard Clauses、命名规范 | 适用于所有语言/范式        |\n",
    "| **模块级** | 关注点分离、面向接口、端口-适配器、组件化、插件化            | OO、函数式、脚本语言均适用 |\n",
    "| **协作级** | CQRS、事件驱动、Actor/消息队列、数据流编程、Pipeline         | 更偏向函数式/并发/分布式   |\n",
    "| **架构级** | Clean Architecture、Hexagonal、微服务、DDD、Serverless、Data-Oriented Arch | 依赖领域和运行环境         |\n",
    "| **过程级** | 测试驱动开发（TDD）、演进式设计、持续集成、DevOps、文档驱动设计 | 面向团队的工程实践         |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 面向接口与回调/消息机制的关联"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "你提到的文章强调“function/bind 只是泛型函数指针”只是表象，真正的价值在于：\n",
    "\n",
    "- **回调（callback）/代理（delegate）**：允许对象把响应绑定到外部接口，而不是固化在继承层次中。\n",
    "- **信号与消息传递**：将“发送消息”的动作抽象成接口或事件，符合 迪米特法则 + 面向接口思想。\n",
    "- **动态消息机制**：Smalltalk、Objective-C、COM、现代事件总线都借助消息驱动来避免强耦合。\n",
    "\n",
    "因此，面向接口如果实现得当，可以直接让系统靠高阶函数、事件、数据管道协作，不需要先定义庞大的继承体系。这与“设计模式失宠”不是一回事，而是回归“组件+消息”的本质，设计模式只是“语言不足时的补丁”这一观点和文章作者是一致的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 结论与建议"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. **设计原则远不止面向对象**，按范式、层次还有大量可用原则与实践。关注点分离、函数式原则、事件驱动、数据导向等都是直接可用的工具。\n",
    "2. **面向接口不等于无模型，但可以弱化传统模式的地位**。接口+组合+消息驱动的生态同样需要设计，只是更多借助高阶函数、事件、协议等机制，而非继承树。\n",
    "3. **是否用设计模式要看语言特性与团队共识**。若语言直接支持 delegate、mixins、pattern matching，某些经典模式可以被更直接的语言结构取代。\n",
    "4. **推荐重点关注消息传递与组件协作**（即文章中提到的“对象之间互发消息”），不要被静态的类图绑住手脚。C++20 的 `std::function`、`std::bind`, `std::variant`, Concepts 等都在帮我们摆脱继承束缚。\n",
    "5. **保持实践导向：**先以接口、事件、组合让系统跑起来，再在演进中提炼是否需要抽象/模式/模型，避免一开始就陷入“面向类的哲学冥想”。\n",
    "\n",
    "希望这些补充能帮助你在“超越传统 OO 设计模式”的角度上，有更全面的视角与工具箱。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
